﻿namespace Smart.Utils.UI.BarcodeLib
{
    using System;
    using System.Collections.Generic;
    using System.Data;

    internal class Code128 : BarcodeCommon, IBarcode
    {
        private List<string> _EncodedData;
        private List<string> _FormattedData;
        private DataTable C128_Code;
        private DataRow StartCharacter;
        private TYPES type;

        public Code128(string input)
        {
            this.C128_Code = new DataTable("C128");
            this._FormattedData = new List<string>();
            this._EncodedData = new List<string>();
            this.StartCharacter = null;
            this.type = TYPES.DYNAMIC;
            base.Raw_Data = input;
        }

        public Code128(string input, TYPES type)
        {
            this.C128_Code = new DataTable("C128");
            this._FormattedData = new List<string>();
            this._EncodedData = new List<string>();
            this.StartCharacter = null;
            this.type = TYPES.DYNAMIC;
            this.type = type;
            base.Raw_Data = input;
        }

        private void BreakUpDataForEncoding()
        {
            string item = "";
            string str2 = base.Raw_Data;
            if ((this.type == TYPES.A) || (this.type == TYPES.B))
            {
                foreach (char ch in base.Raw_Data)
                {
                    this._FormattedData.Add(ch.ToString());
                }
            }
            else
            {
                if (this.type == TYPES.C)
                {
                    try
                    {
                        Convert.ToInt64(base.Raw_Data);
                    }
                    catch
                    {
                        throw new Exception("EC128-6: Only numeric values can be encoded with C128-C.");
                    }
                    if ((base.Raw_Data.Length % 2) > 0)
                    {
                        str2 = "0" + base.Raw_Data;
                    }
                }
                foreach (char ch in str2)
                {
                    if (char.IsNumber(ch))
                    {
                        if (item == "")
                        {
                            item = item + ch;
                        }
                        else
                        {
                            item = item + ch;
                            this._FormattedData.Add(item);
                            item = "";
                        }
                    }
                    else
                    {
                        if (item != "")
                        {
                            this._FormattedData.Add(item);
                            item = "";
                        }
                        this._FormattedData.Add(ch.ToString());
                    }
                }
                if (item != "")
                {
                    this._FormattedData.Add(item);
                    item = "";
                }
            }
        }

        private string CalculateCheckDigit()
        {
            string str = this._FormattedData[0];
            uint num = 0;
            for (uint i = 0; i < this._FormattedData.Count; i++)
            {
                string str2 = this._FormattedData[(int) i].Replace("'", "''");
                DataRow[] rowArray = this.C128_Code.Select("A = '" + str2 + "'");
                if (rowArray.Length <= 0)
                {
                    rowArray = this.C128_Code.Select("B = '" + str2 + "'");
                }
                if (rowArray.Length <= 0)
                {
                    rowArray = this.C128_Code.Select("C = '" + str2 + "'");
                }
                uint num4 = uint.Parse(rowArray[0]["Value"].ToString()) * ((i == 0) ? 1 : i);
                num += num4;
            }
            uint num5 = num % 0x67;
            return this.C128_Code.Select("Value = '" + num5.ToString() + "'")[0]["Encoding"].ToString();
        }

        private string Encode_Code128()
        {
            this.init_Code128();
            return this.GetEncoding();
        }

        private List<DataRow> FindStartorCodeCharacter(string s, ref int col)
        {
            List<DataRow> list = new List<DataRow>();
            if (((s.Length > 1) && char.IsNumber(s[0])) && char.IsNumber(s[1]))
            {
                if (this.StartCharacter == null)
                {
                    this.StartCharacter = this.C128_Code.Select("A = 'START_C'")[0];
                    list.Add(this.StartCharacter);
                }
                else
                {
                    list.Add(this.C128_Code.Select("A = 'CODE_C'")[0]);
                }
                col = 1;
                return list;
            }
            bool flag = false;
            bool flag2 = false;
            foreach (DataRow row in this.C128_Code.Rows)
            {
                try
                {
                    if (!flag && (s == row["A"].ToString()))
                    {
                        flag = true;
                        col = 2;
                        if (this.StartCharacter == null)
                        {
                            this.StartCharacter = this.C128_Code.Select("A = 'START_A'")[0];
                            list.Add(this.StartCharacter);
                        }
                        else
                        {
                            list.Add(this.C128_Code.Select("B = 'CODE_A'")[0]);
                        }
                    }
                    else if (!flag2 && (s == row["B"].ToString()))
                    {
                        flag2 = true;
                        col = 1;
                        if (this.StartCharacter == null)
                        {
                            this.StartCharacter = this.C128_Code.Select("A = 'START_B'")[0];
                            list.Add(this.StartCharacter);
                        }
                        else
                        {
                            list.Add(this.C128_Code.Select("A = 'CODE_B'")[0]);
                        }
                    }
                    else if (flag && flag2)
                    {
                        break;
                    }
                }
                catch (Exception exception)
                {
                    throw new Exception("EC128-1: " + exception.Message);
                }
            }
            if (list.Count <= 0)
            {
                throw new Exception("EC128-2: Could not determine start character.");
            }
            return list;
        }

        private string GetEncoding()
        {
            this.BreakUpDataForEncoding();
            this.InsertStartandCodeCharacters();
            string str = this.CalculateCheckDigit();
            string str2 = "";
            foreach (string str3 in this._FormattedData)
            {
                DataRow[] rowArray;
                string str4 = str3.Replace("'", "''");
                switch (this.type)
                {
                    case TYPES.DYNAMIC:
                        rowArray = this.C128_Code.Select("A = '" + str4 + "'");
                        if (rowArray.Length <= 0)
                        {
                            rowArray = this.C128_Code.Select("B = '" + str4 + "'");
                            if (rowArray.Length <= 0)
                            {
                                rowArray = this.C128_Code.Select("C = '" + str4 + "'");
                            }
                        }
                        break;

                    case TYPES.A:
                        rowArray = this.C128_Code.Select("A = '" + str4 + "'");
                        break;

                    case TYPES.B:
                        rowArray = this.C128_Code.Select("B = '" + str4 + "'");
                        break;

                    case TYPES.C:
                        rowArray = this.C128_Code.Select("C = '" + str4 + "'");
                        break;

                    default:
                        rowArray = null;
                        break;
                }
                if ((rowArray == null) || (rowArray.Length <= 0))
                {
                    throw new Exception("EC128-5: Could not find encoding of a value( " + str4 + " ) in C128 type " + this.type.ToString());
                }
                str2 = str2 + rowArray[0]["Encoding"].ToString();
                this._EncodedData.Add(rowArray[0]["Encoding"].ToString());
            }
            str2 = str2 + this.CalculateCheckDigit();
            this._EncodedData.Add(this.CalculateCheckDigit());
            str2 = str2 + this.C128_Code.Select("A = 'STOP'")[0]["Encoding"].ToString();
            this._EncodedData.Add(this.C128_Code.Select("A = 'STOP'")[0]["Encoding"].ToString());
            str2 = str2 + "11";
            this._EncodedData.Add("11");
            return str2;
        }

        private void init_Code128()
        {
            this.C128_Code.CaseSensitive = true;
            this.C128_Code.Columns.Add("Value", typeof(string));
            this.C128_Code.Columns.Add("A", typeof(string));
            this.C128_Code.Columns.Add("B", typeof(string));
            this.C128_Code.Columns.Add("C", typeof(string));
            this.C128_Code.Columns.Add("Encoding", typeof(string));
            this.C128_Code.Rows.Add(new object[] { "0", " ", " ", "00", "11011001100" });
            this.C128_Code.Rows.Add(new object[] { "1", "!", "!", "01", "11001101100" });
            this.C128_Code.Rows.Add(new object[] { "2", "\"", "\"", "02", "11001100110" });
            this.C128_Code.Rows.Add(new object[] { "3", "#", "#", "03", "10010011000" });
            this.C128_Code.Rows.Add(new object[] { "4", "$", "$", "04", "10010001100" });
            this.C128_Code.Rows.Add(new object[] { "5", "%", "%", "05", "10001001100" });
            this.C128_Code.Rows.Add(new object[] { "6", "&", "&", "06", "10011001000" });
            this.C128_Code.Rows.Add(new object[] { "7", "'", "'", "07", "10011000100" });
            this.C128_Code.Rows.Add(new object[] { "8", "(", "(", "08", "10001100100" });
            this.C128_Code.Rows.Add(new object[] { "9", ")", ")", "09", "11001001000" });
            this.C128_Code.Rows.Add(new object[] { "10", "*", "*", "10", "11001000100" });
            this.C128_Code.Rows.Add(new object[] { "11", "+", "+", "11", "11000100100" });
            this.C128_Code.Rows.Add(new object[] { "12", ",", ",", "12", "10110011100" });
            this.C128_Code.Rows.Add(new object[] { "13", "-", "-", "13", "10011011100" });
            this.C128_Code.Rows.Add(new object[] { "14", ".", ".", "14", "10011001110" });
            this.C128_Code.Rows.Add(new object[] { "15", "/", "/", "15", "10111001100" });
            this.C128_Code.Rows.Add(new object[] { "16", "0", "0", "16", "10011101100" });
            this.C128_Code.Rows.Add(new object[] { "17", "1", "1", "17", "10011100110" });
            this.C128_Code.Rows.Add(new object[] { "18", "2", "2", "18", "11001110010" });
            this.C128_Code.Rows.Add(new object[] { "19", "3", "3", "19", "11001011100" });
            this.C128_Code.Rows.Add(new object[] { "20", "4", "4", "20", "11001001110" });
            this.C128_Code.Rows.Add(new object[] { "21", "5", "5", "21", "11011100100" });
            this.C128_Code.Rows.Add(new object[] { "22", "6", "6", "22", "11001110100" });
            this.C128_Code.Rows.Add(new object[] { "23", "7", "7", "23", "11101101110" });
            this.C128_Code.Rows.Add(new object[] { "24", "8", "8", "24", "11101001100" });
            this.C128_Code.Rows.Add(new object[] { "25", "9", "9", "25", "11100101100" });
            this.C128_Code.Rows.Add(new object[] { "26", ":", ":", "26", "11100100110" });
            this.C128_Code.Rows.Add(new object[] { "27", ";", ";", "27", "11101100100" });
            this.C128_Code.Rows.Add(new object[] { "28", "<", "<", "28", "11100110100" });
            this.C128_Code.Rows.Add(new object[] { "29", "=", "=", "29", "11100110010" });
            this.C128_Code.Rows.Add(new object[] { "30", ">", ">", "30", "11011011000" });
            this.C128_Code.Rows.Add(new object[] { "31", "?", "?", "31", "11011000110" });
            this.C128_Code.Rows.Add(new object[] { "32", "@", "@", "32", "11000110110" });
            this.C128_Code.Rows.Add(new object[] { "33", "A", "A", "33", "10100011000" });
            this.C128_Code.Rows.Add(new object[] { "34", "B", "B", "34", "10001011000" });
            this.C128_Code.Rows.Add(new object[] { "35", "C", "C", "35", "10001000110" });
            this.C128_Code.Rows.Add(new object[] { "36", "D", "D", "36", "10110001000" });
            this.C128_Code.Rows.Add(new object[] { "37", "E", "E", "37", "10001101000" });
            this.C128_Code.Rows.Add(new object[] { "38", "F", "F", "38", "10001100010" });
            this.C128_Code.Rows.Add(new object[] { "39", "G", "G", "39", "11010001000" });
            this.C128_Code.Rows.Add(new object[] { "40", "H", "H", "40", "11000101000" });
            this.C128_Code.Rows.Add(new object[] { "41", "I", "I", "41", "11000100010" });
            this.C128_Code.Rows.Add(new object[] { "42", "J", "J", "42", "10110111000" });
            this.C128_Code.Rows.Add(new object[] { "43", "K", "K", "43", "10110001110" });
            this.C128_Code.Rows.Add(new object[] { "44", "L", "L", "44", "10001101110" });
            this.C128_Code.Rows.Add(new object[] { "45", "M", "M", "45", "10111011000" });
            this.C128_Code.Rows.Add(new object[] { "46", "N", "N", "46", "10111000110" });
            this.C128_Code.Rows.Add(new object[] { "47", "O", "O", "47", "10001110110" });
            this.C128_Code.Rows.Add(new object[] { "48", "P", "P", "48", "11101110110" });
            this.C128_Code.Rows.Add(new object[] { "49", "Q", "Q", "49", "11010001110" });
            this.C128_Code.Rows.Add(new object[] { "50", "R", "R", "50", "11000101110" });
            this.C128_Code.Rows.Add(new object[] { "51", "S", "S", "51", "11011101000" });
            this.C128_Code.Rows.Add(new object[] { "52", "T", "T", "52", "11011100010" });
            this.C128_Code.Rows.Add(new object[] { "53", "U", "U", "53", "11011101110" });
            this.C128_Code.Rows.Add(new object[] { "54", "V", "V", "54", "11101011000" });
            this.C128_Code.Rows.Add(new object[] { "55", "W", "W", "55", "11101000110" });
            this.C128_Code.Rows.Add(new object[] { "56", "X", "X", "56", "11100010110" });
            this.C128_Code.Rows.Add(new object[] { "57", "Y", "Y", "57", "11101101000" });
            this.C128_Code.Rows.Add(new object[] { "58", "Z", "U", "58", "11101100010" });
            this.C128_Code.Rows.Add(new object[] { "59", "[", "[", "59", "11100011010" });
            this.C128_Code.Rows.Add(new object[] { "60", @"\", @"\", "60", "11101111010" });
            this.C128_Code.Rows.Add(new object[] { "61", "]", "]", "61", "11001000010" });
            this.C128_Code.Rows.Add(new object[] { "62", "^", "^", "62", "11110001010" });
            this.C128_Code.Rows.Add(new object[] { "63", "_", "_", "63", "10100110000" });
            this.C128_Code.Rows.Add(new object[] { "64", "\0", "`", "64", "10100001100" });
            this.C128_Code.Rows.Add(new object[] { "65", Convert.ToChar(1).ToString(), "a", "65", "10010110000" });
            this.C128_Code.Rows.Add(new object[] { "66", Convert.ToChar(2).ToString(), "b", "66", "10010000110" });
            this.C128_Code.Rows.Add(new object[] { "67", Convert.ToChar(3).ToString(), "c", "67", "10000101100" });
            this.C128_Code.Rows.Add(new object[] { "68", Convert.ToChar(4).ToString(), "d", "68", "10000100110" });
            this.C128_Code.Rows.Add(new object[] { "69", Convert.ToChar(5).ToString(), "e", "69", "10110010000" });
            this.C128_Code.Rows.Add(new object[] { "70", Convert.ToChar(6).ToString(), "f", "70", "10110000100" });
            this.C128_Code.Rows.Add(new object[] { "71", Convert.ToChar(7).ToString(), "g", "71", "10011010000" });
            this.C128_Code.Rows.Add(new object[] { "72", Convert.ToChar(8).ToString(), "h", "72", "10011000010" });
            this.C128_Code.Rows.Add(new object[] { "73", Convert.ToChar(9).ToString(), "i", "73", "10000110100" });
            this.C128_Code.Rows.Add(new object[] { "74", Convert.ToChar(10).ToString(), "j", "74", "10000110010" });
            this.C128_Code.Rows.Add(new object[] { "75", Convert.ToChar(11).ToString(), "k", "75", "11000010010" });
            this.C128_Code.Rows.Add(new object[] { "76", Convert.ToChar(12).ToString(), "l", "76", "11001010000" });
            this.C128_Code.Rows.Add(new object[] { "77", Convert.ToChar(13).ToString(), "m", "77", "11110111010" });
            this.C128_Code.Rows.Add(new object[] { "78", Convert.ToChar(14).ToString(), "n", "78", "11000010100" });
            this.C128_Code.Rows.Add(new object[] { "79", Convert.ToChar(15).ToString(), "o", "79", "10001111010" });
            this.C128_Code.Rows.Add(new object[] { "80", Convert.ToChar(0x10).ToString(), "p", "80", "10100111100" });
            this.C128_Code.Rows.Add(new object[] { "81", Convert.ToChar(0x11).ToString(), "q", "81", "10010111100" });
            this.C128_Code.Rows.Add(new object[] { "82", Convert.ToChar(0x12).ToString(), "r", "82", "10010011110" });
            this.C128_Code.Rows.Add(new object[] { "83", Convert.ToChar(0x13).ToString(), "s", "83", "10111100100" });
            this.C128_Code.Rows.Add(new object[] { "84", Convert.ToChar(20).ToString(), "t", "84", "10011110100" });
            this.C128_Code.Rows.Add(new object[] { "85", Convert.ToChar(0x15).ToString(), "u", "85", "10011110010" });
            this.C128_Code.Rows.Add(new object[] { "86", Convert.ToChar(0x16).ToString(), "v", "86", "11110100100" });
            this.C128_Code.Rows.Add(new object[] { "87", Convert.ToChar(0x17).ToString(), "w", "87", "11110010100" });
            this.C128_Code.Rows.Add(new object[] { "88", Convert.ToChar(0x18).ToString(), "x", "88", "11110010010" });
            this.C128_Code.Rows.Add(new object[] { "89", Convert.ToChar(0x19).ToString(), "y", "89", "11011011110" });
            this.C128_Code.Rows.Add(new object[] { "90", Convert.ToChar(0x1a).ToString(), "z", "90", "11011110110" });
            this.C128_Code.Rows.Add(new object[] { "91", Convert.ToChar(0x1b).ToString(), "{", "91", "11110110110" });
            this.C128_Code.Rows.Add(new object[] { "92", Convert.ToChar(0x1c).ToString(), "|", "92", "10101111000" });
            this.C128_Code.Rows.Add(new object[] { "93", Convert.ToChar(0x1d).ToString(), "}", "93", "10100011110" });
            this.C128_Code.Rows.Add(new object[] { "94", Convert.ToChar(30).ToString(), "~", "94", "10001011110" });
            this.C128_Code.Rows.Add(new object[] { "95", Convert.ToChar(0x1f).ToString(), Convert.ToChar(0x7f).ToString(), "95", "10111101000" });
            this.C128_Code.Rows.Add(new object[] { "96", Convert.ToChar(0xca).ToString(), Convert.ToChar(0xca).ToString(), "96", "10111100010" });
            this.C128_Code.Rows.Add(new object[] { "97", Convert.ToChar(0xc9).ToString(), Convert.ToChar(0xc9).ToString(), "97", "11110101000" });
            this.C128_Code.Rows.Add(new object[] { "98", "SHIFT", "SHIFT", "98", "11110100010" });
            this.C128_Code.Rows.Add(new object[] { "99", "CODE_C", "CODE_C", "99", "10111011110" });
            this.C128_Code.Rows.Add(new object[] { "100", "CODE_B", Convert.ToChar(0xcb).ToString(), "CODE_B", "10111101110" });
            this.C128_Code.Rows.Add(new object[] { "101", Convert.ToChar(0xcb).ToString(), "CODE_A", "CODE_A", "11101011110" });
            this.C128_Code.Rows.Add(new object[] { "102", Convert.ToChar(200).ToString(), Convert.ToChar(200).ToString(), Convert.ToChar(200).ToString(), "11110101110" });
            this.C128_Code.Rows.Add(new object[] { "103", "START_A", "START_A", "START_A", "11010000100" });
            this.C128_Code.Rows.Add(new object[] { "104", "START_B", "START_B", "START_B", "11010010000" });
            this.C128_Code.Rows.Add(new object[] { "105", "START_C", "START_C", "START_C", "11010011100" });
            this.C128_Code.Rows.Add(new object[] { "", "STOP", "STOP", "STOP", "11000111010" });
        }

        private void InsertStartandCodeCharacters()
        {
            DataRow row = null;
            string str = "";
            switch (this.type)
            {
                case TYPES.A:
                    this._FormattedData.Insert(0, "START_A");
                    break;

                case TYPES.B:
                    this._FormattedData.Insert(0, "START_B");
                    break;

                case TYPES.C:
                    this._FormattedData.Insert(0, "START_C");
                    break;

                case TYPES.DYNAMIC:
                    try
                    {
                        for (int i = 0; i < this._FormattedData.Count; i++)
                        {
                            int col = 0;
                            List<DataRow> list = this.FindStartorCodeCharacter(this._FormattedData[i], ref col);
                            bool flag = false;
                            foreach (DataRow row2 in list)
                            {
                                if ((row2["A"].ToString().EndsWith(str) || row2["B"].ToString().EndsWith(str)) || row2["C"].ToString().EndsWith(str))
                                {
                                    flag = true;
                                    break;
                                }
                            }
                            if ((str == "") || !flag)
                            {
                                row = list[0];
                                bool flag2 = true;
                                while (flag2)
                                {
                                    try
                                    {
                                        str = row[col].ToString().Split(new char[] { '_' })[1];
                                        flag2 = false;
                                    }
                                    catch
                                    {
                                        flag2 = true;
                                        if (col++ > row.ItemArray.Length)
                                        {
                                            throw new Exception("No start character found in CurrentCodeSet.");
                                        }
                                    }
                                }
                                this._FormattedData.Insert(i++, row[col].ToString());
                            }
                        }
                    }
                    catch (Exception exception)
                    {
                        throw new Exception("EC128-3: Could not insert start and code characters.\n Message: " + exception.Message);
                    }
                    break;

                default:
                    throw new Exception("EC128-4: Unknown start type in fixed type encoding.");
            }
        }

        public string Encoded_Value
        {
            get
            {
                return this.Encode_Code128();
            }
        }

        public enum TYPES
        {
            DYNAMIC,
            A,
            B,
            C
        }
    }
}

